local heyan = fk.CreateSkill{
  name = "hanqing__heyan",
  dynamic_desc = function(self, player)
    if player:getMark(self.name) > 0 then
      return "hanqing__heyan_inner"
    end
  end,
}

Fk:loadTranslationTable{
  ["hanqing__heyan"] = "和言",
  [":hanqing__heyan"] = "当一张拼点牌或判定牌亮出时，你可以将一张手牌与之交换，若改变了拼点输赢或判定花色，你摸一张牌，然后本技能改为每轮限一次。",

  [":hanqing__heyan_inner"] = "每轮限一次，当一张拼点牌或判定牌亮出时，你可以将一张手牌与之交换，若改变了拼点输赢或判定花色，你摸一张牌。",

  ["#hanqing__heyan-ask"] = "和言：是否用一张手牌替换 %dest 的“%arg”判定牌？",
  ["#hanqing__heyan-pindian"] = "和言：是否用一张手牌替换一名角色的拼点牌？",
  ["#HQHeyanChangePindian"] = "%from 将 %to 的拼点牌替换为 %arg",
}

Fk:addPoxiMethod{
  name = "hanqing__heyan",
  prompt = "#hanqing__heyan-pindian",
  card_filter = function (to_select, selected, data, extra_data)
    if #selected < 2 then
      if #selected == 0 then
        return true
      else
        if table.contains(data[#data][2], selected[1]) then
          return not table.contains(data[#data][2], to_select)
        else
          return table.contains(data[#data][2], to_select)
        end
      end
    end
  end,
  feasible = function(selected, data)
    if data and #selected == 2 then
      if table.contains(data[#data][2], selected[1]) then
        return not table.contains(data[#data][2], selected[2])
      else
        return table.contains(data[#data][2], selected[2])
      end
    end
  end,
}

heyan:addEffect(fk.AskForRetrial, {
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(heyan.name) and not player:isKongcheng() then
      if player:getMark(heyan.name) > 0 then
        return player:usedSkillTimes(heyan.name, Player.HistoryRound) == 0
      else
        return true
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local card = room:askToCards(player, {
      min_num = 1,
      max_num = 1,
      include_equip = false,
      skill_name = heyan.name,
      prompt = "#hanqing__heyan-ask::"..target.id..":"..data.reason,
      cancelable = true,
    })
    if #card > 0 then
      event:setCostData(self, {cards = card})
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local orig_card = data.card
    local new_card = Fk:getCardById(event:getCostData(self).cards[1])
    room:changeJudge{
      card = new_card,
      player = player,
      data = data,
      skillName = heyan.name,
      exchange = true,
    }
    if not player.dead and orig_card and orig_card:compareSuitWith(new_card, true) then
      room:setPlayerMark(player, heyan.name, 1)
      player:drawCards(1, heyan.name)
    end
  end,
})

-- 将拼点牌变为虚拟牌
---@param card Card
local virtualize = function (card)
  local _card = card:clone(card.suit, card.number)
  if card:getEffectiveId() then
    _card.subcards = { card:getEffectiveId() }
  end
  return _card
end

heyan:addEffect(fk.PindianCardsDisplayed, {
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(heyan.name) and not player:isKongcheng() then
      if player:getMark(heyan.name) > 0 then
        return player:usedSkillTimes(heyan.name, Player.HistoryRound) == 0
      else
        return true
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local card_data = {{data.from.general, {data.fromCard:getEffectiveId()}}}
    for _, p in ipairs(room.players) do
      if data.results[p] then
        table.insert(card_data, {p.general, {data.results[p].toCard:getEffectiveId()}})
      end
    end
    table.insert(card_data, {"$Hand", player:getCardIds("h")})
    local result = room:askToPoxi(player, {
      poxi_type = heyan.name,
      data = card_data,
      cancelable = true,
    })
    if #result == 2 then
      event:setCostData(self, {cards = result})
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local cards = event:getCostData(self).cards
    local new_card = table.find(cards, function (id)
      return table.contains(player:getCardIds("h"), id)
    end)
    if new_card == nil then return end
    table.removeOne(cards, new_card)
    new_card = virtualize(Fk:getCardById(new_card))
    local orig_id = cards[1]
    local orig_card
    local yes = false
    if data.fromCard and data.fromCard:getEffectiveId() == orig_id then
      orig_card = data.fromCard
      room:sendLog{
        type = "#HQHeyanChangePindian",
        from = player.id,
        to = {data.from.id},
        arg = new_card:toLogString(),
      }
      for _, result in pairs(data.results) do
        if orig_card and
          ((orig_card.number > result.toCard.number and new_card.number <= result.toCard.number) or
          (orig_card.number <= result.toCard.number and new_card.number > result.toCard.number)) then
          yes = true
          break
        end
      end
      data.fromCard = new_card
    else
      for _, p in ipairs(room.players) do
        if data.results[p] and data.results[p].toCard:getEffectiveId() == orig_id then
          orig_card = data.results[p].toCard
          room:sendLog{
            type = "#HQHeyanChangePindian",
            from = player.id,
            to = {p.id},
            arg = new_card:toLogString(),
          }
          if orig_card and
            ((orig_card.number > data.fromCard.number and new_card.number <= data.fromCard.number) or
            (orig_card.number <= data.fromCard.number and new_card.number > data.fromCard.number)) then
            yes = true
          end
          data.results[p].toCard = new_card
          break
        end
      end
    end
    local moves = {{
      ids = { new_card:getEffectiveId() },
      from = player,
      toArea = Card.Processing,
      moveReason = fk.ReasonJustMove,
      skillName = data.reason,
      moveVisible = true,
    },
    {
      ids = { orig_card:getEffectiveId() },
      fromArea = Card.Processing,
      to = player,
      toArea = Card.PlayerHand,
      moveReason = fk.ReasonJustMove,
      skillName = data.reason,
      moveVisible = true,
    }}
    room:moveCards(table.unpack(moves))
    if not player.dead and yes then
      room:setPlayerMark(player, heyan.name, 1)
      player:drawCards(1, heyan.name)
    end
  end,
})

return heyan
